﻿using System;
using System.Disposables;
using System.Linq;
using System.Windows.Ria;

namespace SoftSource.Ria
{
    public static class OperationBaseEx
    {
        public static IObservable<T> ToObservable<T>(Func<Action<T>, T> handler) where T : OperationBase
        {
            return Observable.CreateWithDisposable<T>(observer =>
                {
                    object gate = new object();
                    bool canceled = false;
                    MutableDisposable mutable = new MutableDisposable();

                    var operation = handler(
                        t =>
                        {
                            lock (gate)
                            {
                                if (canceled)
                                    return;
                            }

                            if (t.HasError)
                            {                               
                                mutable.Replace(Observable
                                    .Throw<T>(t.Error)
                                    .Do(value => t.MarkErrorAsHandled())
                                    .Subscribe(observer));
                            }
                            else
                            {
                                mutable.Replace(Observable
                                    .Return<T>(t)
                                    .Subscribe(observer));
                            }
                        });

                    mutable.Replace(Disposable.Create(() =>
                        {
                            lock (gate)
                            {
                                if (operation.CanCancel)
                                    operation.Cancel();
                                canceled = true;
                            }
                        }));

                    return mutable;
                });
        }
    }
}
